home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / GX Libraries / ConicLibrary.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-31  |  4.1 KB  |  152 lines  |  [TEXT/MPS ]

  1.  
  2. /*
  3.     File:        ConicLibrary.c
  4.  
  5.     Contains:    graphics libraries - conic library
  6.  
  7.     Written by:    Mike Reed
  8.  
  9.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.          <1>      1/9/95    JD        First checked in.
  14. */
  15.  
  16. #include "GraphicsLibraries.h"
  17.  
  18. /*
  19.  *  kNumPoints must be at least 2^n + 2 where n is kMaxRecursion.
  20.  *  Current static implementation limits ctr bits to 1 long so
  21.  *  kMaxRecursion cannot be greater than 4
  22.  */
  23. #define kMaxRecursion       4
  24.  
  25. #define kNumPoints          ((1L << kMaxRecursion) + 2)
  26.  
  27. #define kNumOfStaticLongs   (2 + kNumPoints*2)
  28.  
  29. /*
  30.  *  This dude just does what it says.  I broke up some of the formulas
  31.  *  to try and reduce overflow of intermediate results.  This is a good
  32.  *  place to optimize with assembler for speed and accuracy.
  33.  */
  34. static void SubdivideConic(register const conic *c, conic *left, conic *rite)
  35. {
  36.     register Fixed lambda = c->lambda;
  37.     register Fixed lambdaPlusOne = lambda + fixed1;
  38.     register Fixed lambdaBx = FixedMultiply(lambda, c->b.x);
  39.     register Fixed lambdaBy = FixedMultiply(lambda, c->b.y);
  40.  
  41.     left->a = c->a;
  42.     left->b.x = FixedDivide(c->a.x + lambdaBx, lambdaPlusOne);
  43.     left->b.y = FixedDivide(c->a.y + lambdaBy, lambdaPlusOne);
  44.  
  45.     left->c.x = FixedDivide((c->a.x + c->c.x >> 1) + lambdaBx, lambdaPlusOne);
  46.     left->c.y = FixedDivide((c->a.y + c->c.y >> 1) + lambdaBy, lambdaPlusOne);
  47.     rite->a = left->c;
  48.  
  49.     rite->b.x = FixedDivide(c->c.x + lambdaBx, lambdaPlusOne);
  50.     rite->b.y = FixedDivide(c->c.y + lambdaBy, lambdaPlusOne);
  51.     rite->c = c->c;
  52.  
  53.     left->lambda = rite->lambda = FixedSquareRoot(lambdaPlusOne >> 1);
  54. }
  55. /*
  56.  *  This guy fills out ptPtr with ON/OFF-gxCurve points.  recursion is the maximum
  57.  *  depth I can call myself, since storage for ptPtr is pre-allocated.
  58.  */
  59. static gxPoint* Conic2Path(const conic *aConic, gxPoint *ptPtr, short recursion)
  60. {
  61.     if ((recursion-- > 0))
  62.     {
  63.         conic leftConic, riteConic;
  64.         SubdivideConic(aConic, &leftConic, &riteConic);
  65.         ptPtr = Conic2Path(&leftConic, ptPtr, recursion);
  66.         ptPtr = Conic2Path(&riteConic, ptPtr, recursion);
  67.     }
  68.     else
  69.     {
  70.         *ptPtr++ = aConic->b;
  71.     }
  72.     return ptPtr;
  73. }
  74.  
  75. /*
  76.  *  The lambda for a parabola is 1.  Error should be
  77.  *      (a - 2b + c) (lambda - 1)
  78.  *      -----------------------
  79.  *               8
  80.  */
  81. static short RecursionDepth(register const conic *aConic, register Fixed tolerance)
  82. {
  83.     register Fixed dx, dy;
  84.  
  85.     {
  86.         register Fixed tmp = aConic->lambda - fixed1 + 4 >> 3;
  87.         dx = aConic->b.x;
  88.         dx = FixedMultiply( aConic->a.x - dx - dx + aConic->c.x, tmp );
  89.         dy = aConic->b.y;
  90.         dy = FixedMultiply( aConic->a.y - dy - dy + aConic->c.y, tmp );
  91.     }
  92.     {
  93.         register short count;
  94.         register Fixed length = Magnitude( dx, dy );
  95.         for (count = 0; length > tolerance; count++)
  96.             length >>= 4;
  97.         return count;
  98.     }
  99. }
  100.  
  101. /*
  102.  *  Given a conic geometry, returns a gxPath
  103.  */
  104. static void ConicPath(long *storage, const conic *aConic)
  105. {
  106.     Fixed       tolerance = GXGetShapeCurveError( GXGetDefaultShape(gxPathType) );
  107.     gxPoint*  ptPtr;
  108.     long*   longp = storage;
  109.     short   count;
  110.  
  111.     count = RecursionDepth(aConic, tolerance);
  112.     if (count > kMaxRecursion)
  113.         count = kMaxRecursion;
  114.  
  115.     ptPtr = (gxPoint*)&storage[2];
  116.     *ptPtr++ = aConic->a;
  117.     ptPtr = Conic2Path(aConic, ptPtr, count);
  118.     *ptPtr++ = aConic->c;
  119.  
  120.     count = ptPtr - (gxPoint*)&storage[2];
  121.     storage[0] = count;
  122.     storage[1] = 0x7FFFFFFF ^ ( 1L << 32 - count );
  123. }
  124.  
  125. /***********************************************************************/
  126.  
  127. void DrawConic(const conic *aConic, gxShapeFill aFill)
  128. {
  129.     gxShape s = NewConic(aConic);
  130.     if (aFill)
  131.         GXSetShapeFill(s, aFill);
  132.     GXSetShapeAttributes(s, GXGetShapeAttributes(s) & ~gxCachedShape);
  133.     GXDrawShape(s);
  134.     GXDisposeShape(s);
  135. }
  136.  
  137. gxShape NewConic(const conic *aConic)
  138. {
  139.     long    storage[kNumOfStaticLongs];
  140.     
  141.     ConicPath(storage, aConic);
  142.     return NewPath((gxPath*)storage);
  143. }
  144.  
  145. void SetConic(gxShape dest, const conic *aConic)
  146. {
  147.     long    storage[kNumOfStaticLongs];
  148.     
  149.     ConicPath(storage, aConic);
  150.     SetPath(dest, 0, (gxPath*)storage);
  151. }
  152.